<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="../../public/css/bootstrap-utilities.css" />
        <link rel="stylesheet" href="../../public/css/bootstrap.min.css" />
        <link rel="stylesheet" href="../../public/css/bootstrap-icons.css" />
        <link rel="stylesheet" href="../../public/css/element-plus.css" />
        <link rel="stylesheet" href="../../public/css/theme.css" />

        <script src="../../public/js/echarts/echarts.js"></script>
        <script src="../../public/js/echarts/macarons.js"></script>
        <script src="../../public/js/echarts/dark.js"></script>
        <script src="../../public/js/vue/vue.global.prod.js"></script>
        <script src="../../public/js/element-plus.js"></script>
        <script src="../../components/icon-svg.js"></script>
        <script src="../../components/lepton.js"></script>
    </head>
    <body class="theme">
        <svg id="lepton-svgs"></svg>
        <div id="app" v-cloak>
            <!-- 基础信息 -->
            <div class="p-2x2 v-start gap-2">
                <div class="h-start">
                    <span class="w-char-4">服务器:</span>
                    <span class="text-nowrap user-select-all">{{stats.name}}</span>
                </div>
                <div class="h-start">
                    <span class="w-char-4">IP:</span>
                    <span class="user-select-all text-nowrap user-select-all">{{stats.ip}}</span>
                </div>
                <div class="h-start">
                    <span class="w-char-4">状态:</span>
                    <div>
                        <div class="h-start-center gap-2">
                            <icon-svg :name="state.icon" size="15px"></icon-svg>
                            <div>{{state.name}}</div>
                        </div>
                        <div>{{stats.error}}</div>
                    </div>
                </div>
                <div class="h-start">
                    <span class="w-char-4">心跳:</span>
                    <span class="h-start-center gap-2">
                        <icon-svg name="heartbeat" size="15px"></icon-svg>
                        <span class="text-nowrap">{{stats.duration}}ms</span>
                    </span>
                </div>
                <div class="h-start">
                    <span class="w-char-4">操作系统:</span>
                    <span class="user-select-all text-nowrap user-select-all">{{stats.os}}</span>
                </div>
                <div class="h-start">
                    <span class="w-char-4">系统版本:</span>
                    <span class="user-select-all text-nowrap user-select-all">
                        {{stats.osVersion}}
                    </span>
                </div>
                <div class="h-start">
                    <span class="w-char-4">运行时间:</span>
                    <span class="user-select-all text-nowrap">{{stats.upTotalTime}}</span>
                </div>
                <div class="h-start">
                    <button class="btn btn-info" @click="hasDetail = !hasDetail">更多</button>
                </div>
                <div v-if="hasDetail" class="v-start gap-2">
                    <div class="h-start">
                        <span class="w-char-4">用户数量:</span>
                        <span class="text-nowrap">{{stats.userTotal}}</span>
                    </div>
                    <div class="h-start">
                        <span class="w-char-4">负载-1m:</span>
                        <span class="text-nowrap">{{loadAvg?.m01}}</span>
                    </div>
                    <div class="h-start">
                        <span class="w-char-4">负载-5m:</span>
                        <span class="text-nowrap">{{loadAvg?.m05}}</span>
                    </div>
                    <div class="h-start">
                        <span class="w-char-4">负载-10m:</span>
                        <span class="text-nowrap">{{loadAvg?.m10}}</span>
                    </div>
                    <div class="h-start">
                        <span class="w-char-4">运行进程:</span>
                        <span class="text-nowrap">{{loadAvg?.process_run}}</span>
                    </div>
                    <div class="h-start">
                        <span class="w-char-4">进程总数:</span>
                        <span class="text-nowrap">{{loadAvg?.process_total}}</span>
                    </div>
                    <div class="h-start">
                        <span class="w-char-4">最新进程:</span>
                        <span class="text-nowrap user-select-all">
                            {{loadAvg?.process_last_create_id}}
                        </span>
                    </div>
                </div>
            </div>
            <!-- 选择指标 -->
            <div class="p-2x2">
                <div class="h-start gap-2">
                    <button
                        class="btn btn-primary"
                        v-for="(item,index) in metricGroup"
                        :key="item.id"
                        @click="tabChange(item,index)">
                        {{metricFor(item.id)}}
                    </button>
                </div>
                <el-checkbox-group v-if="tab" v-model="ids" class="v-start mt-2" @change="change">
                    <el-checkbox
                        class="mb-0"
                        v-for="child in tab.children"
                        :key="child.id"
                        :value="child.id"
                        :label="metricFor(child.id)" />
                </el-checkbox-group>
            </div>
            <!-- 已选指标 -->
            <div class="p-2x2" v-if="ids.length > 0">
                <div class="fs-8 fw-bold">已选指标</div>
                <div class="h-start gap-2 mt-2">
                    <el-tag
                        v-for="(item,index) in selected"
                        type="primary"
                        closable
                        @close="close(item.id)">
                        {{metricFor(item.id)}}
                    </el-tag>
                </div>
            </div>
            <!-- 变化图表 -->
            <div class="p-2x2">
                <div class="h-between-center gap-1">
                    <div class="fs-8 fw-bold">变化图表</div>
                    <el-radio-group
                        v-model="refreshInterval.chart"
                        class="h-start gap-2"
                        @change="changeChartInterval">
                        <el-radio
                            class="m-0"
                            v-for="item in refreshChart"
                            :key="item.value"
                            :value="item.value">
                            {{item.label}}
                        </el-radio>
                    </el-radio-group>
                </div>
                <div class="mt-2">
                    <div
                        class="chart"
                        v-for="item in enableCharts"
                        :id="item.id"
                        :key="item.id"></div>
                </div>
            </div>
            <!-- 进程列表 -->
            <div class="p-2x2" v-if="ids.includes('process_')">
                <div class="h-between-center gap-1">
                    <div>
                        <span class="fs-8 fw-bold">进程列表</span>
                        <span class="ms-1 fs-10">{{process.time}}</span>
                    </div>
                    <el-radio-group
                        v-model="refreshInterval.process"
                        class="h-start gap-2"
                        @change="changeProcessInterval">
                        <el-radio
                            class="m-0"
                            v-for="item in refreshProcess"
                            :key="item.value"
                            :value="item.value">
                            {{item.label}}
                        </el-radio>
                    </el-radio-group>
                </div>
                <el-table
                    class="w-100 mt-2"
                    size="small"
                    row-key="pid"
                    :data="process.items"
                    stripe
                    border
                    max-height="500">
                    <el-table-column
                        type="index"
                        align="center"
                        :index="1"
                        min-width="50"></el-table-column>
                    <el-table-column
                        prop="pid"
                        label="PID"
                        align="center"
                        width="70"
                        sortable></el-table-column>
                    <el-table-column prop="user" label="用户" align="center"></el-table-column>
                    <el-table-column
                        prop="cpu_usage"
                        label="CPU%"
                        align="center"
                        sortable></el-table-column>
                    <el-table-column
                        prop="mem_usage"
                        label="内存%"
                        sortable
                        align="center"></el-table-column>
                    <el-table-column
                        prop="vsz"
                        label="虚拟内存(KB)"
                        align="center"
                        min-width="95"></el-table-column>
                    <el-table-column
                        prop="rss"
                        label="物理内存(KB)"
                        align="center"
                        min-width="95"></el-table-column>
                    <el-table-column prop="tty" label="终端" align="center"></el-table-column>
                    <el-table-column prop="stat" label="状态" align="center"></el-table-column>
                    <el-table-column
                        prop="start_time"
                        label="启动时间"
                        align="center"
                        min-width="90"
                        sortable></el-table-column>
                    <el-table-column
                        prop="time"
                        label="CPU累计"
                        align="center"
                        min-width="70"
                        show-overflow-tooltip></el-table-column>
                    <el-table-column
                        prop="command"
                        label="命令"
                        align="left"
                        header-align="center"
                        show-overflow-tooltip></el-table-column>
                    <el-table-column label="操作" align="center" fixed="right">
                        <template #default="scope">
                            <el-button size="small" type="danger" @click="stopProcess(scope.row)">
                                停止
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
            <!-- 用户列表 -->
            <div class="p-2x2" v-if="ids.includes('user_')">
                <div class="h-between-center gap-1">
                    <span class="fs-8 fw-bold">用户列表</span>
                    <span class="fs-9 fw-bold">共{{users.length}}个用户</span>
                </div>
                <el-table
                    class="w-100 mt-2"
                    size="small"
                    row-key="user"
                    :data="users"
                    stripe
                    border
                    max-height="500">
                    <el-table-column
                        type="index"
                        align="center"
                        :index="1"
                        min-width="50"></el-table-column>
                    <el-table-column
                        prop="user"
                        label="用户名"
                        align="center"
                        min-width="80"
                        show-overflow-tooltip
                        sortable></el-table-column>
                    <el-table-column
                        prop="uid"
                        label="用户ID"
                        align="center"
                        min-width="80"
                        sortable></el-table-column>
                    <el-table-column
                        prop="gid"
                        label="用户组ID"
                        sortable
                        min-width="100"
                        align="center"></el-table-column>

                    <el-table-column
                        prop="home"
                        label="主目录"
                        align="left"
                        show-overflow-tooltip
                        min-width="80"></el-table-column>
                    <el-table-column
                        prop="shell"
                        label="终端"
                        align="left"
                        show-overflow-tooltip
                        min-width="80"></el-table-column>
                    <el-table-column
                        prop="remark"
                        label="备注"
                        align="center"
                        show-overflow-tooltip></el-table-column>
                    <el-table-column label="操作" align="center" fixed="right" min-width="125">
                        <template #default="scope">
                            <el-button
                                v-if="scope.row.user != 'root'"
                                size="small"
                                type="danger"
                                @click="lockUser(scope.row)">
                                锁定
                            </el-button>
                            <el-button
                                v-if="scope.row.user != 'root'"
                                size="small"
                                type="success"
                                @click="unlockUser(scope.row)">
                                解锁
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
        </div>
        <script src="../../public/icons/offline-icon.js"></script>
        <script src="../../public/icons/online-icon.js"></script>
        <script src="../../public/icons/heartbeat-icon.js"></script>
        <script>
            const charts = []

            const { createApp, nextTick, toRaw } = Vue
            const app = createApp({
                data() {
                    return {
                        stats: {
                            name: '',
                            ip: '',
                            status: 'WAITING',
                            error: '',
                            rtt: '',
                            duration: -1,
                            os: -1,
                            osVersion: -1,
                            time: -1,
                            time_ms: -1,
                            upTotalTime: -1,
                            upTotalFreeTime: -1,
                            userTotal: -1
                        },
                        ids: [],
                        hasDetail: false,
                        metrics: [
                            {
                                prefix: 'mem',
                                metric: {
                                    total: {
                                        title: '总容量',
                                        unit: 'MB'
                                    },
                                    used: {
                                        title: '已用',
                                        unit: 'MB'
                                    },
                                    free: {
                                        title: '空闲',
                                        unit: 'MB'
                                    },
                                    shared: {
                                        title: '共享',
                                        unit: 'MB'
                                    },
                                    'buff/cache': {
                                        title: '缓存',
                                        unit: 'MB'
                                    },
                                    available: {
                                        title: '可用',
                                        unit: 'MB'
                                    },
                                    usedRatio: {
                                        title: '使用率',
                                        unit: '%',
                                        selected: true
                                    },
                                    freeRatio: {
                                        title: '空闲率',
                                        unit: '%'
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/mem_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return '内存'
                                    } else {
                                        return '内存 - ' + name
                                    }
                                }
                            },
                            {
                                prefix: 'hdd',
                                metric: {
                                    reads_completed_count: {
                                        title: '已完成读取次数',
                                        unit: '次'
                                    },
                                    reads_merged_count: {
                                        title: '合并读取次数',
                                        unit: '次'
                                    },
                                    sectors_read: {
                                        title: '读取扇区数',
                                        unit: '个'
                                    },
                                    ms_reading: {
                                        title: '读取耗时',
                                        unit: '毫秒'
                                    },
                                    writes_completed_count: {
                                        title: '已完成写入次数',
                                        unit: '次'
                                    },
                                    writes_merged_count: {
                                        title: '合并写入次数',
                                        unit: '次'
                                    },
                                    sectors_written: {
                                        title: '写入扇区数',
                                        unit: '个'
                                    },
                                    ms_writing: {
                                        title: '写入耗时',
                                        unit: '毫秒'
                                    },
                                    ios_in_progress: {
                                        title: '进行中的IO请求数',
                                        unit: ''
                                    },
                                    ms_spent_doing_io: {
                                        title: '花费的IO时间',
                                        unit: '毫秒'
                                    },
                                    ms_spent_doing_weighted_io: {
                                        title: '加权IO时间',
                                        unit: '毫秒'
                                    },
                                    read_speed: {
                                        title: '读取速度',
                                        unit: 'B/s'
                                    },
                                    write_speed: {
                                        title: '写入速度',
                                        unit: 'B/s'
                                    },
                                    read_speed_mb: {
                                        title: '读取速度',
                                        unit: 'MB/s',
                                        selected: true
                                    },
                                    write_speed_mb: {
                                        title: '写入速度',
                                        unit: 'MB/s',
                                        selected: true
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/hdd_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return '磁盘'
                                    } else {
                                        return '磁盘 - ' + name
                                    }
                                }
                            },
                            {
                                prefix: 'net',
                                metric: {
                                    down_bytes: {
                                        title: '下行字节数',
                                        unit: 'B'
                                    },
                                    down_packets: {
                                        title: '下行包数',
                                        unit: '个'
                                    },
                                    down_errs: {
                                        title: '下行错误数',
                                        unit: '个'
                                    },
                                    down_drop: {
                                        title: '下行丢包数',
                                        unit: '个'
                                    },
                                    down_fifo: {
                                        title: '下行FIFO数',
                                        unit: '个'
                                    },
                                    down_frame: {
                                        title: '下行帧错误数',
                                        unit: '个'
                                    },
                                    down_compressed: {
                                        title: '下行压缩数据量',
                                        unit: 'B'
                                    },
                                    up_bytes: {
                                        title: '上行字节数',
                                        unit: 'B'
                                    },
                                    up_packets: {
                                        title: '上行包数',
                                        unit: '个'
                                    },
                                    up_errs: {
                                        title: '上行错误数',
                                        unit: '个'
                                    },
                                    up_drop: {
                                        title: '上行丢包数',
                                        unit: '个'
                                    },
                                    up_fifo: {
                                        title: '上行FIFO数',
                                        unit: '个'
                                    },
                                    up_colls: {
                                        title: '上行冲突数',
                                        unit: '个'
                                    },
                                    up_carrier: {
                                        title: '上行载波检测',
                                        unit: ''
                                    },
                                    up_compressed: {
                                        title: '上行压缩数据量',
                                        unit: 'B'
                                    },
                                    down_speed: {
                                        title: '下行速度',
                                        unit: 'KB/s',
                                        selected: true
                                    },
                                    up_speed: {
                                        title: '上行速度',
                                        unit: 'KB/s',
                                        selected: true
                                    },
                                    down_packet_speed: {
                                        title: '下行包速率',
                                        unit: '包/秒'
                                    },
                                    up_packet_speed: {
                                        title: '上行包速率',
                                        unit: '包/秒'
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/net_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return '网络'
                                    } else {
                                        return '网络 - ' + name
                                    }
                                }
                            },
                            {
                                prefix: 'cpu',
                                metric: {
                                    user: {
                                        title: '用户态时间',
                                        unit: '时间片'
                                    },
                                    nice: {
                                        title: '低优先级用户态时间',
                                        unit: '时间片'
                                    },
                                    system: {
                                        title: '内核态时间',
                                        unit: '时间片'
                                    },
                                    idle: {
                                        title: '空闲时间',
                                        unit: '时间片'
                                    },
                                    iowait: {
                                        title: '等待I/O时间',
                                        unit: '时间片'
                                    },
                                    irq: {
                                        title: '硬中断时间',
                                        unit: '时间片'
                                    },
                                    softirq: {
                                        title: '软中断时间',
                                        unit: '时间片'
                                    },
                                    steal: {
                                        title: '虚拟机抢占时间',
                                        unit: '时间片'
                                    },
                                    guest: {
                                        title: '运行虚拟机时间',
                                        unit: '时间片'
                                    },
                                    guest_nice: {
                                        title: '低优先级虚拟机时间',
                                        unit: '时间片'
                                    },
                                    total: {
                                        title: '总时间',
                                        unit: '时间片'
                                    },
                                    usedRatio: {
                                        title: '占用率',
                                        unit: '%',
                                        selected: true
                                    },
                                    idleRatio: {
                                        title: '空闲率',
                                        unit: '%'
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/cpu_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return 'CPU'
                                    } else {
                                        return 'CPU - ' + name
                                    }
                                }
                            },
                            {
                                prefix: 'process',
                                metric: {
                                    process: {
                                        title: '所有进程',
                                        unit: ''
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/process_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return '进程'
                                    } else {
                                        return '进程 - ' + name
                                    }
                                }
                            },
                            {
                                prefix: 'user',
                                metric: {
                                    user: {
                                        title: '所有用户',
                                        unit: ''
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/user_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return '用户'
                                    } else {
                                        return '用户 - ' + name
                                    }
                                }
                            },
                            {
                                prefix: 'load-avg_',
                                metric: {
                                    m01: {
                                        title: '1分钟',
                                        unit: '',
                                        selected: true
                                    },
                                    m05: {
                                        title: '5分钟',
                                        unit: '',
                                        selected: true
                                    },
                                    m10: {
                                        title: '10分钟',
                                        unit: '',
                                        selected: true
                                    },
                                    process_run: {
                                        title: '运行中',
                                        unit: '个'
                                    },
                                    process_total: {
                                        title: '总进程',
                                        unit: '个'
                                    },
                                    process_last_create_id: {
                                        title: '最新进程ID',
                                        unit: ''
                                    }
                                },
                                fn(id) {
                                    let match = id.match(/load-avg_(.*)/)
                                    let name = match[1]
                                    if (name == '') {
                                        return '负载'
                                    } else {
                                        return '负载 - ' + name
                                    }
                                }
                            }
                        ],
                        process: {
                            columns: [
                                {
                                    key: 'user',
                                    dataKey: 'user',
                                    title: '用户',
                                    align: 'center',
                                    minWidth: 50,
                                    flexGrow: 1
                                },
                                {
                                    key: 'pid',
                                    dataKey: 'pid',
                                    title: 'PID',
                                    align: 'center',
                                    sortable: true,
                                    minWidth: 50,
                                    flexGrow: 1
                                },
                                {
                                    key: 'cpu_usage',
                                    dataKey: 'cpu_usage',
                                    title: 'CPU%',
                                    align: 'center',
                                    sortable: true,
                                    flexGrow: 1
                                },
                                {
                                    key: 'mem_usage',
                                    dataKey: 'mem_usage',
                                    title: '内存%',
                                    align: 'center',
                                    sortable: true,
                                    flexGrow: 1
                                },
                                {
                                    key: 'vsz',
                                    dataKey: 'vsz',
                                    title: '虚拟KB',
                                    align: 'center',
                                    sortable: true,
                                    flexGrow: 1
                                },
                                {
                                    key: 'rss',
                                    dataKey: 'rss',
                                    title: '物理KB',
                                    align: 'center',
                                    sortable: true,
                                    flexGrow: 1
                                },
                                {
                                    key: 'tty',
                                    dataKey: 'tty',
                                    title: '终端',
                                    align: 'center',
                                    flexGrow: 1
                                },
                                {
                                    key: 'stat',
                                    dataKey: 'stat',
                                    title: '状态',
                                    align: 'center',
                                    flexGrow: 1
                                },
                                {
                                    key: 'start_time',
                                    dataKey: 'start_time',
                                    title: '启动时间',
                                    align: 'center',
                                    sortable: true,
                                    flexGrow: 1
                                },
                                {
                                    key: 'time',
                                    dataKey: 'time',
                                    title: 'CPU累计',
                                    align: 'center',
                                    sortable: true,
                                    flexGrow: 1
                                },
                                {
                                    key: 'command',
                                    dataKey: 'command',
                                    title: '命令',
                                    align: 'left',
                                    resizable: true,
                                    flexGrow: 1,
                                    ellipsis: {
                                        tooltip: true
                                    }
                                },
                                {
                                    title: '操作',
                                    key: 'action',
                                    dataKey: 'action',
                                    align: 'center',
                                    fixed: 'right'
                                }
                            ],
                            items: [],
                            time: ''
                        },
                        metricGroup: [],
                        refreshChart: [
                            {
                                id: 'refresh-chart-0s',
                                value: 0,
                                label: '心跳'
                            },
                            {
                                id: 'refresh-chart-1s',
                                value: 1,
                                label: '1秒'
                            },
                            {
                                id: 'refresh-chart-5s',
                                value: 5,
                                label: '5秒'
                            },
                            {
                                id: 'refresh-chart-30s',
                                value: 30,
                                label: '30秒'
                            },
                            {
                                id: 'refresh-chart-1m',
                                value: 60,
                                label: '1分'
                            }
                        ],
                        refreshProcess: [
                            {
                                id: 'refresh-process-0s',
                                value: 0,
                                label: '心跳'
                            },
                            {
                                id: 'refresh-process-1s',
                                value: 1,
                                label: '1秒'
                            },
                            {
                                id: 'refresh-process-5s',
                                value: 5,
                                label: '5秒'
                            },

                            {
                                id: 'refresh-process-30s',
                                value: 30,
                                label: '30秒'
                            },
                            {
                                id: 'refresh-process-5m',
                                value: 60 * 5,
                                label: '5分'
                            }
                        ],
                        refreshInterval: {
                            chart: 1,
                            process: 5
                        },
                        theme: 'macarons',
                        tabIndex: 0,
                        loadAvg: {},
                        users: []
                    }
                },
                computed: {
                    state() {
                        let data = {
                            name: '',
                            icon: ''
                        }
                        switch (this.stats.status) {
                            case 'WAITING':
                                data.name = '等待中'
                                data.icon = 'offline'
                                break
                            case 'SUCCESS':
                                data.name = '在线'
                                data.icon = 'online'
                                break
                            case 'ERROR':
                                data.name = '离线'
                                data.icon = 'offline'
                                break
                        }
                        return data
                    },
                    selected() {
                        let enables = []
                        let map = new Map(
                            this.metricGroup.flatMap(it =>
                                it.children.map(child => [child.id, child])
                            )
                        )
                        this.ids.forEach(id => {
                            let item = map.get(id)
                            if (item) {
                                enables.push(item)
                            }
                        })
                        return enables
                    },
                    enableCharts() {
                        return this.selected.filter(it => !it.noChart)
                    },
                    tab() {
                        return this.metricGroup[this.tabIndex]
                    }
                },
                mounted() {
                    this.initChannel()
                },
                methods: {
                    async onInit() {
                        this.stats = await this.onFn('onInit')
                    },
                    close(id) {
                        let index = this.ids.indexOf(id)
                        if (index != -1) {
                            this.ids.splice(index, 1)
                            this.onFn('changeUserCharts', toRaw(this.ids))
                        }
                    },
                    tabChange(item, index) {
                        this.tabIndex = index
                    },
                    onThemeChanged(name) {
                        switch (name) {
                            case 'Monokai':
                                this.theme = 'dark'
                                break
                            default:
                                this.theme = 'macarons'
                                break
                        }
                        charts.forEach(it => {
                            it.chart.dispose()

                            it.chart = echarts.init(document.getElementById(it.id), this.theme)
                            it.chart.setOption(it.option)
                        })
                    },
                    setMetricGroup({ metricGroup, ids, chartInterval, processInterval }) {
                        this.metricGroup = metricGroup
                        this.ids = ids
                        this.refreshInterval.chart = chartInterval
                        this.refreshInterval.process = processInterval
                        this.change()
                    },
                    change() {
                        console.log(this.ids)
                        let items = []
                        let set = new Set()
                        let ids = new Set(this.enableCharts.map(it => it.id))
                        charts.forEach(it => {
                            if (ids.has(it.id)) {
                                items.push(it)
                                set.add(it.id)
                            } else {
                                it.chart.dispose()
                                it.chart.clear()
                            }
                        })
                        charts.length = 0
                        charts.push(...items)
                        nextTick(() => {
                            ids.forEach(id => {
                                if (!set.has(id)) {
                                    this.initChart(id, this.metricFor(id))
                                }
                            })
                        })
                        this.onFn('changeUserCharts', toRaw(this.ids))
                    },
                    setStats(stats) {
                        Object.assign(this.stats, stats)
                    },
                    setProcess({ items, time }) {
                        this.process.items = items
                        this.process.time = time
                        console.log(items)
                    },
                    metricFor(id, name) {
                        let item = this.metrics.find(it => id.startsWith(it.prefix))
                        if (name) {
                            if (item) {
                                let opts = item.metric[name]
                                if (opts) {
                                    return opts
                                }
                            }
                            return {
                                title: name,
                                unit: ''
                            }
                        }
                        if (item) {
                            return item.fn(id)
                        }
                        return id
                    },
                    initChart(id, title) {
                        const data = []
                        const option = {
                            title: {
                                text: title,
                                textStyle: {
                                    fontSize: 14
                                }
                            },
                            legend: {},
                            toolbox: {
                                show: true,
                                feature: {
                                    dataView: {
                                        readOnly: false
                                    },
                                    magicType: {
                                        type: ['line', 'area', 'bar']
                                    }
                                }
                            },

                            tooltip: {
                                trigger: 'axis',
                                axisPointer: {
                                    type: 'cross'
                                },
                                formatter: (params, ticket, callback) => {
                                    let items = Array.isArray(params) ? params : [params]
                                    if (items.length === 0) {
                                        return
                                    }
                                    let time = items[0].axisValueLabel ?? 'N/A'
                                    let html = `<div>
                                                    <h5>${time}</h5>
                                                    <table>
                                                        <tbody>`
                                    items.forEach(it => {
                                        let metric = this.metricFor(id, it.seriesName)
                                        let marker = it.marker
                                        let title = metric?.title ?? 'N/A'
                                        let value = it.data[it.seriesName] ?? 'N/A'
                                        let unit = metric?.unit ?? 'N/A'
                                        html += `   <tr>
                                                        <td>${marker}</td>
                                                        <td>${title}</td>
                                                        <td style="padding-left: 8px;">${value}</td>
                                                        <td style="padding-left: 8px;">${unit}</td>
                                                    </tr>`
                                    })
                                    html += `       </tbody>
                                                </table>
                                            </div>`
                                    return html
                                }
                            },
                            dataset: {
                                source: data
                            },
                            grid: {
                                left: 0,
                                right: 0
                            },
                            xAxis: {
                                type: 'category',
                                boundaryGap: false,
                                axisTick: {
                                    alignWithLabel: true,
                                    show: true
                                }
                            },
                            yAxis: {
                                splitLine: {
                                    show: false
                                }
                            },
                            series: []
                        }
                        const chart = echarts.init(document.getElementById(id), this.theme)
                        chart.setOption(option)
                        function append(point, opt) {
                            const width = chart.getWidth()
                            const max = Math.floor(width / 50)
                            data.push(point)
                            if (data.length > max) {
                                data.splice(0, data.length - max)
                            }
                            if (opt) {
                                Object.assign(option, opt)
                            }
                            chart.setOption({
                                dataset: {
                                    source: data
                                },
                                ...opt
                            })
                        }
                        charts.push({
                            chart,
                            id,
                            option,
                            append
                        })
                        window.addEventListener('resize', chart.resize)
                    },
                    appendPoint({ id, data }) {
                        let chart = charts.find(it => it.id == id)
                        if (chart) {
                            if (chart.option.series.length > 0) {
                                chart.append(data)
                            } else {
                                const series = []
                                for (const name in data) {
                                    if (['time', 'timespan', 'time_ms', 'name'].includes(name)) {
                                        continue
                                    }
                                    series.push({
                                        name: name,
                                        type: 'line',
                                        smooth: true,
                                        areaStyle: {},
                                        encode: {
                                            x: 'time',
                                            y: name
                                        }
                                    })
                                }
                                let selected = {}
                                let item = this.metrics.find(it => id.startsWith(it.prefix))
                                if (item) {
                                    for (const name in item.metric) {
                                        const opts = item.metric[name]
                                        selected[name] = !!opts.selected
                                    }
                                }
                                chart.append(data, {
                                    legend: {
                                        type: 'scroll',
                                        selected,
                                        formatter: name => {
                                            let metric = this.metricFor(id, name)
                                            return metric.title
                                        }
                                    },
                                    series
                                })
                            }
                        }
                    },
                    changeChartInterval(item) {
                        console.log(item)
                        this.onFn('changeChartInterval', item)
                    },
                    changeProcessInterval(item) {
                        console.log(item)
                        this.onFn('changeProcessInterval', item)
                    },
                    setLoadAvg(value) {
                        this.loadAvg = value
                    },
                    setUsers({ items }) {
                        this.users = items
                    },
                    stopProcess(item) {
                        this.onFn('stopProcess', {
                            pid: item.pid,
                            name: item.command
                        })
                    },
                    lockUser(item) {
                        this.onFn('lockUser', {
                            user: item.user
                        })
                    },
                    unlockUser(item) {
                        this.onFn('unlockUser', {
                            user: item.user
                        })
                    }
                }
            })
            app.use(window.lepton)
            app.use(window.ElementPlus)
            app.mount('#app')
        </script>
    </body>
</html>
